package com.xjoyt.pay.share.services;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.xjoyt.pay.abstracts.AbstractService;
import com.xjoyt.pay.commons.ObjectUtils;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.dto.PageParam;
import com.xjoyt.pay.dto.PageResult;
import com.xjoyt.pay.share.api.ali.area.AreaClient;
import com.xjoyt.pay.share.api.ali.area.dto.ApiAreaItem;
import com.xjoyt.pay.share.params.AreaPageParam;
import com.xjoyt.pay.share.po.Area;
import com.xjoyt.pay.share.repository.AreaRepository;

@Service
public class AreaService extends AbstractService {

	private static String KEY_AREA_ACTION_FETCH = "key:area.action.fetch";

	@Autowired
	private AreaRepository repository;

	@Autowired
	private AreaClient areaClient;

	@Autowired
	private StringRedisTemplate redisTemplate;

	public Area get(String id) {
		return repository.findOne(id);
	}

	public PageResult<Area> loadPage(PageParam<AreaPageParam> param) {
		return repository.loadPage(param);
	}

	public ExecuteResult<Area> save(Area entity) {
		if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
			return ExecuteResult.fail("抓取任务正在执行，无法修改只读数据");
		}
		return ExecuteResult.ok(repository.save(entity));
	}

	public ExecuteResult<?> remove(String id) {
		if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
			return ExecuteResult.fail("抓取任务正在执行，无法修改只读数据");
		}
		repository.delete(id);
		return ExecuteResult.ok();
	}

	public List<Area> findAllByParentId(String parentId) {
		return repository.findAllByParentId(parentId);
	}

	public ExecuteResult<?> fetch(String key, String parentId) throws Exception {
		if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
			return ExecuteResult.fail("任务已执行，无法重复执行");
		}
		Area entity = repository.findOne(parentId);
		if (entity == null) {
			return ExecuteResult.fail("数据不存在");
		}
		runFetch(key, parentId, StringUtils.isBlank(entity.path) ? parentId : entity.path);
		return ExecuteResult.ok();
	}

	public ExecuteResult<?> fetch(String key) throws Exception {
		if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
			return ExecuteResult.fail("任务已执行，无法重复执行");
		}

		runFetch(key, "0", StringUtils.EMPTY);
		return ExecuteResult.ok();
	}

	private void runFetch(String key, String parentId, String path) {
		ExecutorService threadPool = Executors.newCachedThreadPool();
		FutureTask<Object> future = new FutureTask<>(() -> {
			if (StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
				return ExecuteResult.fail("任务已执行，无法重复执行");
			}
			redisTemplate.opsForValue().set(KEY_AREA_ACTION_FETCH, "go");
			try {
				fetchByParentId(key, parentId, path);
			} finally {
				redisTemplate.delete(KEY_AREA_ACTION_FETCH);
			}

			return null;
		});
		threadPool.execute(future);
	}

	private void fetchByParentId(String key, String parentId, String path) {
		try {
			// 判断任务是否终止
			if (StringUtils.isBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
				return;
			}

			Thread.sleep(500);
			List<ApiAreaItem> items = areaClient.getAreaIems(key, parentId);
			if (CollectionUtils.isEmpty(items))
				return;
			items.forEach(item -> {
				Area entity = new Area();
				ObjectUtils.fieldCopy(item, entity);
				entity.path = StringUtils.isBlank(path) ? parentId : (path + "@" + parentId);
				entity.lon = NumberUtils.toDouble(item.lon);
				entity.lat = NumberUtils.toDouble(item.lat);
				repository.save(entity);
				if (StringUtils.isNotBlank(item.parentId)) {
					fetchByParentId(key, entity.id, entity.path);
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public ExecuteResult<Boolean> isRunFetch() {
		boolean result = StringUtils.isNotBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH));
		return ExecuteResult.ok(result);
	}

	public ExecuteResult<?> stopFetch() {
		if (StringUtils.isBlank(redisTemplate.opsForValue().get(KEY_AREA_ACTION_FETCH))) {
			return ExecuteResult.fail("无正在执行的任务");
		}

		redisTemplate.delete(KEY_AREA_ACTION_FETCH);
		return ExecuteResult.ok();
	}
}
